<template>
	<conf-module-container-cameras :show-page-tools="true">
		<template #Slot-Conf-Module-Header>
			<p class="operations-title font-20-bold">报警器管理</p>
		</template>

		<template #Slot-Conf-Module-Tools-Left>
			<div style="display: flex; align-items: center; justify-content: space-between; margin-bottom: 20px">
				<div style="display: flex; align-items: center; gap: 8px">
					<global-input-search
						v-model:value="tableAttr.searchObj.nameOrIp"
						placeholder="设备名称、设备IP"
						style="width: 216px"
						allow-clear
						@search="setTableData(true)"
					></global-input-search>
					<global-switch-tab :status-data="queryStatusList" @switch-tab="switchTab"></global-switch-tab>
				</div>
				<div style="display: flex; align-items: center; gap: 8px">
					<a-tooltip placement="top" :title="'关闭/开启已配置算法的声光报警器警报功能'">
						<a-button v-if="g6Permission.showBtn('algo-alarm-control')" @click="algoAlarmControl"> 算法报警控制 </a-button>
					</a-tooltip>
					<a-tooltip placement="top" :title="'请在添加完成所需摄像头后，再与声光报警器进行绑定，否则无法绑定成功'">
						<a-button v-if="g6Permission.showBtn('upload-config')" type="primary" @click="handleUploadClick"> 导入配置 </a-button>
					</a-tooltip>
					<input ref="fileInputRef" type="file" style="display: none" accept=".xlsx,.xls" @change="handleFileChange" />
				</div>
			</div>
		</template>

		<template #Slot-Conf-Module-Left>
			<div class="_tree">
				<div class="tree-page-left">
					<div class="_top">
						<div class="tree-left-header font-14-bold">场景位置</div>
						<div style="cursor: pointer" @click="areaOperate('add-default-area')">+</div>
					</div>

					<global-tree :tree-data="treeData" :default-icon="true" :expand-action="'click'" @select="selectTree">
						<template #Slot-Menu-Icon="{ node }">
							<a class="expand-dropdown-link" @click.stop>
								<div class="device-num" style="vertical-align: baseline">
									<!-- ({{
                    cDeviceOnline(
                      node.childrenCopy ? node.childrenCopy : node.children
                    ) || 0
                  }}/{{
                    cDeviceTotal(
                      node.childrenCopy ? node.childrenCopy : node.children
                    ) || 0
                  }}) -->
									{{ `(${node.onLineChildrenCount}/${node.totalChildrenCount})` }}
								</div>
							</a>
						</template>
						<template #Slot-Menu-Btns="{ node }">
							<a-menu v-if="node.name !== '默认区域'" @click="({ key }) => areaOperate(key as string, node)">
								<a-menu-item key="edit-regional" v-if="g6Permission.showBtn('edit-regional')" class="menu-item">
									<p>编辑场景</p>
								</a-menu-item>
								<a-menu-item key="add-same-level-regional" v-if="g6Permission.showBtn('add-same-level-regional')" class="menu-item">
									<p>新增同级</p>
								</a-menu-item>
								<a-menu-item
									key="add-lower-level-regional"
									v-if="node.level !== 5 && g6Permission.showBtn('add-lower-level-regional')"
									class="menu-item"
								>
									<p>新增下级</p>
								</a-menu-item>
								<a-menu-item key="single-delete-regional" v-if="g6Permission.showBtn('single-delete-regional')" class="menu-item">
									<p>删除场景</p>
								</a-menu-item>
							</a-menu>
						</template>
					</global-tree>
				</div>
			</div>
		</template>
		<template #Slot-Conf-Module-Right>
			<div class="table-width">
				<global-table
					:data-source="tableAttr.data"
					:selected-row-keys="tableAttr.selectedKeys"
					:columns="columns"
					:show-operation="true"
					:x-scroll="1100"
					:use-select="true"
					@selected="(rowKeys: any, node: any): any => ((tableAttr.selectedKeys = rowKeys), (nodes = node))"
				>
					<template #name="{ record }">
						<div :class="['ellipsis-text', !record.name && 'ellipsis-text--warning']" :title="record.name">
							{{ record.name || '待命名' }}
						</div>
					</template>
					<template #boxDeviceNames="{ record }">
						<div :class="['ellipsis-text', !record.boxDeviceNames && 'ellipsis-text--warning']" :title="record.boxDeviceNames">
							{{ record.boxDeviceNames || '待绑定' }}
						</div>
					</template>
					<template #operation="{ record }">
						<div class="operations">
							<div
								v-if="g6Permission.showBtn('edit-alarm-equipment')"
								class="font-14 operation-item-btn"
								@click="PageButtonClick('edit-alarm-equipment', record)"
							>
								{{ '编辑' }}
							</div>

							<!-- -->
							<div
								v-if="g6Permission.showBtn('enable-disable') && record.status"
								class="font-14 operation-item-btn"
								@click="PageButtonClick('enable-disable', record)"
							>
								{{ record.enabled ? '禁用' : '启用' }}
							</div>
							<div
								v-if="g6Permission.showBtn('delete-equipment') && !record.status"
								class="font-14 operation-item-btn"
								@click="PageButtonClick('delete-equipment', record)"
							>
								删除
							</div>
						</div>
					</template>

					<template #status="{ record }">
						<div class="item-status" :class="[record.status === 0 ? 'offLine' : 'onLine']">
							{{ record.status == 1 ? '在线' : '离线' }}
						</div>
					</template>
				</global-table>

				<global-pagination
					:style="{
						'padding-bottom': tableAttr.selectedKeys.length !== 0 ? '60px' : '0px'
					}"
					style="margin-left: 20px"
					:current="tableAttr.current"
					:page-size="tableAttr.pageSize"
					:total="tableAttr.total"
					@change="setTablePagination"
				></global-pagination>
			</div>
		</template>

		<template #Slot-Table-Batch-Operation>
			<global-table-batch-operation v-model:selected-rows="tableAttr.selectedKeys">
				<template #Slot-Table-Btns>
					<div class="_button">
						<div style="display: flex; align-items: center" @click="PageButtonClick('regional-set')">
							<global-svg-icon icon-name="share-forward-box-line" width="16px" height="16px" style="margin-right: 6px"></global-svg-icon>
							<p style="color: aliceblue">区域调动</p>
						</div>
					</div>
					<div class="_button">
						<div style="display: flex; align-items: center" @click="PageButtonClick('export-template')">
							<upload-outlined class="btn-icon"></upload-outlined>
							<p style="color: aliceblue">导出模板</p>
						</div>
					</div>
				</template>
			</global-table-batch-operation>
		</template>
	</conf-module-container-cameras>

	<!-- 全屏loading -->
	<div v-if="fullPageLoading" class="config-loading-full">
		<a-spin :spinning="true" :tip="fullPageLoadingText" center>
			<div style="width: 100vw; height: 100vh; background-color: rgba(0, 0, 0, 0.7)"></div>
		</a-spin>
	</div>

	<!-- 分组弹窗 -->
	<a-modal
		v-model:open="groupingCallVisible"
		:title="groupingModalTitle"
		:centered="true"
		width="416px"
		@ok="groupingCallOk"
		@cancel="groupingCancel"
	>
		<a-form ref="formRef" layout="vertical" :model="groupingCallForm" class="operate-form">
			<div v-if="type == 3" style="margin-bottom: 9px; color: #b0b5c0">需要调动的区域</div>

			<a-form-item v-if="groupingType" name="select" :rules="[{ required: true, message: '请选择分组' }]">
				<a-tree-select
					v-model:value="groupingCallForm.select"
					show-search
					style="width: 100%"
					:dropdown-style="{ maxHeight: '400px', overflow: 'auto' }"
					placeholder="请选择分组"
					:field-names="{
						key: 'id',
						value: 'id',
						title: 'name',
						children: 'children'
					}"
					allow-clear
					tree-default-expand-all
					:tree-data="groupingTreeData"
				>
					<template #title="node">
						<a-tooltip>
							<template #title>{{ node.name }}</template>
							<p class="font-14 tree-node-title" style="margin-top: 4px">
								{{ node.name }}
							</p>
						</a-tooltip>
					</template>
				</a-tree-select>
			</a-form-item>
			<a-form-item v-else name="name">
				<div v-if="type == 1" style="margin: 9px; color: #b0b5c0">{{ lowerText }}/</div>
				<a-input v-model:value="groupingCallForm.areaName" autocomplete="off" :maxlength="10" placeholder="请输入"></a-input>
			</a-form-item>
		</a-form>
		<template #footer>
			<a-button size="small" class="btn-default" @click="groupingCancel">取消</a-button>
			<a-button v-if="[3, 4].includes(type)" size="small" type="primary" @click="groupingCallOk">更改</a-button>
			<a-button v-else size="small" type="primary" :loading="loading" @click="groupingCallOk">添加</a-button>
		</template>
	</a-modal>

	<edit-equipment-modal ref="editEquipmentModalRef" :tree-data="treeData" @load-data="setTableData(true)"></edit-equipment-modal>

	<algo-alarm-control-modal ref="AlgoAlarmControlModalRef"></algo-alarm-control-modal>

	<!-- 导入失败弹窗 -->
	<a-modal :open="configFailVisible" :footer="null" :title="'提示'" :width="418" @cancel="configFailVisible = false">
		<div class="config-fail-modal">
			<div class="config-fail"><close-circle-filled class="error-icon"></close-circle-filled>导入配置失败，请下载文件查看失败原因</div>
			<div class="link">
				<a-button class="download-btn" @click="downLoadFailFile">下载文件</a-button>
			</div>
		</div>
	</a-modal>
</template>

<script setup lang="ts" name="cameras-table">
import { g6UseTable } from 'glasssix-vue3-hooks';
import { g6Permission, g6StorageValue } from 'glasssix-utils-ts';
import { useDeleteModal } from '@/global-hooks/base.hooks';
import { getAvOnlineCount, DownloadBlobToAssignFile } from '@/global-utils/base.utils';
import { ConfModuleContainerCameras, EditEquipmentModal, AlgoAlarmControlModal } from '../../components/index';
import { AlarmDeviceManagementAPI } from '../../api';

const loading = ref<boolean>(false);

const fullPageLoading = ref<boolean>(false);
const fullPageLoadingText = ref('');
const configFailVisible = ref<boolean>(false);
const configFailPath = ref<string>();

const editEquipmentModalRef = ref();
const AlgoAlarmControlModalRef = ref();

const { setOpenDeleteModal } = useDeleteModal();
const $message: any = inject('$message');

const groupingCallVisible = ref(false); // 分组调用弹窗
const groupingModalTitle = ref('区域调动'); // 弹窗名称
const treeIsEdit = ref<boolean>(false); // 判断树新增还是编辑

const groupingCallForm = reactive({
	select: undefined,
	areaName: ''
});

const type = ref(1); // 用于判断是否是默认区域新增==>0: 从默认区域增加 1: 新增下级2: 新增同级     ===> 后面这两个用于前端判断的  3:调动区域   4:编辑
const lowerText = ref(''); // 新增下级时输入框前的文字（当前区域名）
const nodes = ref();

// 左侧树按钮弹窗 重置参数
const treeNowNode = reactive({});

const customFormat = (resData: any) => {
	tableAttr.allNums = resData.data.allNums;
	tableAttr.onlineNums = resData.data.onlineNums;
	tableAttr.outlineNums = resData.data.outlineNums;
	tableAttr.data = resData.data.records;
	tableAttr.total = resData.data.total;
};

const { tableAttr, setTableData, setTablePagination } = g6UseTable(AlarmDeviceManagementAPI.list, {}, customFormat);

const columns: TsGlobalType.TsTableColumn[] = [
	{
		dataIndex: 'name',
		title: '设备名称',
		width: 214,
		ellipsis: true,
		custom: true
	},
	{ dataIndex: 'ip', title: '设备IP', width: 214, ellipsis: true },
	{
		dataIndex: 'status',
		title: '状态',
		width: 108,
		ellipsis: true,
		custom: true
	},
	{ dataIndex: 'locationNames', title: '所属区域', width: 170, ellipsis: true },
	{
		dataIndex: 'boxDeviceNames',
		title: '绑定摄像头名称',
		ellipsis: true,
		custom: true
	}
];

/**
 * -----------------------搜索-----------------------
 */
const switchTab = (status: number | null): void => {
	tableAttr.searchObj.status = status;
	g6StorageValue.save('session', 'camerasSwitchTabStatus', status);
	setTableData(true);
};

const algoAlarmControl = () => {
	AlgoAlarmControlModalRef.value?.open();
};
/* ===========================================树操作开始=====================================*/
const treeData = ref([]);
const formRef = ref();
const groupingType = ref<boolean>();
const treeBtnSelect = ref();

// 选中树查列表
const selectTree = async (id: number | string): Promise<void> => {
	tableAttr.searchObj.locationId = id;
	await setTableData(true);
};

// 添加下拉树形key,value
const addTreeAttribute = (arr: any): void => {
	for (let len = 0; len < arr.length; len++) {
		if (arr[len].children) {
			arr[len].disabled = true;
			addTreeAttribute(arr[len].children);
		}
	}
};

// 树接口数据
const getTreeData = async (): Promise<void> => {
	const res: TsRes = await AlarmDeviceManagementAPI.treeData();
	if (res.code === 0 && res.data) {
		treeData.value = treeDataFilter(res.data);
	}
};

const treeDataFilter = (treeData: any) => {
	treeData.forEach((item: any) => {
		item.totalChildrenCount = !item.totalChildrenCount ? 0 : item.totalChildrenCount;
		item.onLineChildrenCount = !item.onLineChildrenCount ? 0 : item.onLineChildrenCount;

		if (item.children && item.children.length) {
			if (item.children[0].type === 2) {
				item.childrenCopy = item.children;
				item.children = null;
			} else {
				treeDataFilter(item.children);
			}
		}
	});
	return treeData;
};

// 区域调动树（有禁用）
const groupingTreeData = ref([]);
const getGroupingTreeData = async (): Promise<void> => {
	// 树接口数据
	const res: TsRes = await AlarmDeviceManagementAPI.treeData();
	if (res.code === 0) {
		groupingTreeData.value = treeDataFilter(res.data);
		addTreeAttribute(groupingTreeData.value);
	}
};

// 树按钮接口参数
const addGroup = async (
	node: any,
	operateObj: {
		isEdit: boolean;
		btnId: number;
		type: number;
	}
) => {
	const { isEdit, btnId, type } = operateObj;
	let res: TsRes = {};
	if (isEdit) {
		let params = {
			areaName: groupingCallForm.areaName,
			id: node.id,
			level: node.level
		};
		res = await AlarmDeviceManagementAPI.editGroup(params);
	} else {
		// 默认 0: 从默认区域增加
		let params = {
			areaName: groupingCallForm.areaName,
			type: type,
			parentIdOrId: 0,
			level: 1
		};
		// 1: 新增下级2: 新增同级
		if (type !== 0) {
			params.parentIdOrId = btnId === 1 ? node.id : node.parentId;
			params.level = btnId === 1 ? node.level + 1 : node.level;
		}
		res = await AlarmDeviceManagementAPI.addGroup(params);
	}
	loading.value = false;
	if (res.code === 0) {
		groupingCallVisible.value = false;
		formRef.value.resetFields();
		getTreeData();
		getGroupingTreeData();
		if (isEdit) {
			$message.success('编辑成功');
		} else {
			$message.success('新增成功');
		}
	}
};

const groupingCancel = (): void => {
	groupingCallVisible.value = false;
};

// 分组调用弹窗确认
const groupingCallOk = (): void => {
	loading.value = true;
	formRef.value
		.validate()
		.then(async () => {
			try {
				if (groupingType.value) {
					// 调动分组接口
					let params = {
						locationId: Number(groupingCallForm.select),
						ids: tableAttr.selectedKeys
					};
					const res: TsRes = await AlarmDeviceManagementAPI.regionMove(params);
					loading.value = false;
					if (res.code === 0) {
						groupingCallVisible.value = false;
						formRef.value.resetFields();
						$message.success('操作成功');
						setTableData();
						await getTreeData();
						await getGroupingTreeData();
					}
				} else {
					// 树按钮新增接口
					addGroup(treeNowNode, {
						isEdit: treeIsEdit.value,
						btnId: treeBtnSelect.value,
						type: type.value
					});
				}
			} catch (error) {
				loading.value = false;
				//
				// eslint-disable-next-line promise/always-return
			}
		})
		.catch((error: any) => {
			console.log('表单提交验证错误', error);
		});
};

const F_TreeGrouping = (node: any, id: number): void => {
	if (id === 3) {
		groupingCallForm.areaName = node.name;
		groupingType.value = false;
		treeIsEdit.value = true;
	}
	Object.assign(treeNowNode, node);
	groupingType.value = false;
	groupingCallVisible.value = true;
};

// 计算设备总数
const cDeviceTotal = computed(() => {
	return (tree: any) => {
		return getAvOnlineCount(tree, 'type');
	};
});

// 计算设备在线数量
const cDeviceOnline = computed(() => {
	return (tree: any) => {
		return getAvOnlineCount(tree, 'status');
	};
});

/* ===========================================树操作结束=====================================*/

// 导入配置文件
const fileInputRef = ref();
const handleFileChange = async (event: any) => {
	const files = event.target.files;
	const formData = new FormData();
	formData.append('file', files[0]);
	fullPageLoading.value = true;
	fullPageLoadingText.value = '配置更新中，请稍等';
	event.target.value = null;
	try {
		let res = await AlarmDeviceManagementAPI.importConfig(formData);
		fullPageLoading.value = false;
		fullPageLoadingText.value = '';
		if (res.data.success) {
			$message.success('批量配置报警器成功！');
			setTableData(true);
			return;
		}
		if (res.data.failedFile) {
			configFailVisible.value = true;
			configFailPath.value = res.data.failedFile;
			setTableData(true);
			return;
		}
		$message.error('批量配置报警器失败');
	} catch (error) {
		console.error(error);
	}
};
const handleUploadClick = () => {
	fileInputRef.value.click();
};

// 导出配置失败的文件
const downLoadFailFile = async () => {
	let param = {
		path: configFailPath.value
	};
	let res = await AlarmDeviceManagementAPI.downloadFailConfig(param);
	DownloadBlobToAssignFile(res.data, '声光报警器批量配置模板.xlsx');
	configFailVisible.value = false;
	configFailPath.value = '';
};

// ---------------------------------------------------

// 页面按钮click
const PageButtonClick = async (btnCode: string, record: Record<string, any> = {}) => {
	const deleteModalInfo = {
		title: '确认删除该报警器？',
		okText: '删除',
		cancelText: '取消'
	};
	const deleteFun = async (): Promise<void> => {
		let params = {
			avDeviceIds: [record.id]
		};
		let res: TsRes = await AlarmDeviceManagementAPI.deleteAlarmDevice(params);
		if (res.code === 0) {
			tableAttr.data = tableAttr.data.filter((row: Record<string, any>) => row.id !== record.id);
			tableAttr.total = tableAttr.total - 1;
			$message.success('删除成功');
			setTableData();
		}
	};

	// 删除设备
	if (btnCode === 'delete-equipment') {
		setOpenDeleteModal(deleteFun, deleteModalInfo);
		return;
	}

	// 启用/禁用设备
	if (btnCode === 'enable-disable') {
		const enableModalInfo = {
			title: '确认启用?',
			okText: '确认',
			cancelText: '取消'
		};
		const disableModalInfo = {
			title: '确认禁用?',
			okText: '确认',
			cancelText: '取消'
		};
		const EnableDisableFun = async (): Promise<void> => {
			const param = {
				avDeviceIds: [record.id],
				enabled: record.enabled === 1 ? 0 : 1
			};
			let res: TsRes = await AlarmDeviceManagementAPI.operateStatus(param);
			if (res.code === 0) {
				$message.success(res.message);
				setTableData();
			}
		};
		record.enabled === 0 ? setOpenDeleteModal(EnableDisableFun, enableModalInfo) : setOpenDeleteModal(EnableDisableFun, disableModalInfo);
	}
	// 编辑设备
	if (btnCode === 'edit-alarm-equipment') {
		editEquipmentModalRef.value?.open(groupingTreeData.value, record);
		return;
	}
	// 区域调动
	if (btnCode === 'regional-set') {
		groupingCallVisible.value = true;
		groupingType.value = true;
		type.value = 3;
		groupingModalTitle.value = '区域调动';
		getGroupingTreeData();
		return;
	}
	// 导出模板

	if (btnCode === 'export-template') {
		let params = { ids: tableAttr.selectedKeys };
		fullPageLoading.value = true;
		let res: TsRes = await AlarmDeviceManagementAPI.exportConfig(params);
		fullPageLoading.value = false;
		DownloadBlobToAssignFile(res.data, '声光报警器批量配置模板.xlsx');
	}
};

// 区域操作
const areaOperate = (btnCode: string, record: Record<string, any> = {}) => {
	const addLowerRegional = async (): Promise<void> => {
		groupingCallVisible.value = true;
	};

	if (btnCode === 'add-default-area') {
		// 新增默认区域按钮
		type.value = 0;
		groupingCallVisible.value = true;
		groupingType.value = false;
		groupingCallForm.areaName = '';
		treeIsEdit.value = false;
		groupingModalTitle.value = '';
		groupingModalTitle.value = '添加场景';
		return;
	}
	if (btnCode === 'add-same-level-regional' || btnCode === 'add-lower-level-regional') {
		const btnId = btnCode === 'add-lower-level-regional' ? 1 : 2;
		treeIsEdit.value = false;
		type.value = btnId;
		groupingCallVisible.value = true;
		groupingCallForm.areaName = '';
		treeBtnSelect.value = btnId;
		groupingModalTitle.value = '添加场景';
		F_TreeGrouping(record, btnId);
		lowerText.value = record.name;

		if (btnCode === 'add-lower-level-regional' && record.hasDevice !== 0) {
			groupingCallVisible.value = false;
			setOpenDeleteModal(addLowerRegional, {
				title: '确认新增场景？新增场景后会把之前场景的摄像头及声光报警器自动划分到新场景下',
				okText: '确定',
				cancelText: '取消'
			});
		}
		return;
	}
	if (btnCode === 'edit-regional') {
		groupingCallVisible.value = true;
		type.value = 4;
		groupingModalTitle.value = '编辑';
		treeIsEdit.value = false;
		F_TreeGrouping(record, 3);
		return;
	}
	if (btnCode === 'single-delete-regional') {
		const deleteRegion = async (): Promise<void> => {
			let res: TsRes = await AlarmDeviceManagementAPI.deleteRegion(record.id);
			if (res.code === 0) {
				$message.success('删除成功');
				getTreeData();
			}
		};
		setOpenDeleteModal(deleteRegion, {
			title: '确认删除场景吗？',
			okText: '删除'
		});
	}
};

// 摄像头状态获取
const queryStatusList = computed(() => {
	let statusData = {
		allNum: tableAttr.allNums,
		onlineNum: tableAttr.onlineNums,
		offNum: tableAttr.outlineNums
	};
	return statusData;
});

onMounted(async () => {
	await setTableData();
	await getTreeData();
	getGroupingTreeData();
});

const watchStop = watch(
	() => groupingCallForm.areaName,
	() => {
		groupingCallForm.areaName = groupingCallForm.areaName.replace(/\s+/, '');
	}
);

onUnmounted(() => {
	watchStop();
});
</script>

<style lang="less" scoped>
:deep(.ant-spin) {
	.ant-spin-text {
		text-shadow: none !important;
	}
}

.ant-select-tree-treenode-disabled {
	color: red !important;
}

.operate-form {
	padding: 40px;
	padding-bottom: 20px;
}

.config-loading-full {
	position: fixed;
	top: 0;
	left: 0;
	z-index: 1999;
	display: flex;
	width: 100%;
	height: 100%;
	justify-content: center;
	align-items: center;
}

.ellipsis-text {
	overflow: hidden;
	width: 100%;
	white-space: nowrap;
	text-overflow: ellipsis;

	&--warning {
		color: @warning01;
	}
}

.config-fail-modal {
	.config-fail {
		display: flex;
		padding: 40px;
		font-size: 14px;
		color: @text01;
		align-items: center;

		.error-icon {
			margin-right: 16px;
			font-size: 20px;
			color: rgba(228, 72, 51, 1);
		}
	}

	.link {
		display: flex;
		padding: 20px 24px;
		padding-bottom: 12px;
		justify-content: center;

		.download-btn {
			border-radius: 8px;
			padding: 8px 16px;
		}
	}
}

.AI-serviceList {
	width: 180px;

	&.active {
		width: 285px;
	}
}

.menu-item {
	background-color: none !important;

	p {
		color: @text02 !important;
	}
}

.ai-name {
	display: flex;
	align-items: center;
	color: @text01;

	.title-type {
		height: 16px !important;
		margin-right: 4px;
		border: 1px solid #a5a9b4;
		border-radius: 8px;
		line-height: 16px;
		color: #0d4cca;
		background: radial-gradient(80.85% 100% at 50% 100%, rgba(221, 235, 255, 0.2) 0%, rgba(234, 243, 255, 0) 100%), #121e30;

		.title-type-text {
			display: flex;
			width: 40px;
			height: 16px !important;
			margin-right: 4px;
			border-radius: 8px;
			padding: 8px 4px;
			font-size: 12px;
			font-weight: 700;
			justify-content: flex-end;
			align-items: center;
			gap: 4px;
		}

		.title-type-number {
			margin-bottom: 2px;
			font-family: 'Alimama FangYuanTi VF';
			font-size: 12px;
			font-weight: 400;
			font-style: normal;
			line-height: 20px; /* 142.857% */
			color: var(--text-01, #fff);

			/* 淡阴影/淡XS */
			text-shadow: 0 1px 4px rgba(2, 36, 59, 0.06);
		}
	}

	.operation-empty {
		// background: rgba(176, 176, 176, 0.8);
		// box-shadow: @shadowS;

		& > span {
			// color: @text03;
		}

		&:hover {
			background: #b0b0b0;
			box-shadow: @shadowM;
		}
	}
}

.item-status {
	position: relative;

	&::before {
		position: absolute;
		top: 9px;
		left: -14px;
		width: 6px;
		height: 6px;
		border-radius: 50%;
		content: '';
	}
}

.offLine {
	&::before {
		background: #ba3b29;
	}
}

.onLine {
	&::before {
		background: #56c763;
	}
}

.ant-select-selector {
	width: 216px !important;
	height: 36px !important;
	line-height: 36px !important;
}

.table-width {
	display: flex;
	width: calc(100% - 10px);
	height: calc(100vh - 76px - 44px - 180px);
	flex-direction: column;
	justify-content: space-between;
}

.operations-title {
	color: rgba(240, 246, 252, 0.95);
}

._tree {
	.tree-page-left {
		height: 100%;
		border-right: 0;
		border-bottom: 0;
		padding-left: -32px !important;
		color: @text02;

		._top {
			display: flex;
			align-items: center;
			justify-content: space-between;
		}

		.tree-left-header {
			height: 38px;
			padding: 4px 16px 4px 0;
			line-height: 30px;
		}
	}
}

.operations {
	display: flex;
	align-items: center;
	width: 100%;
	height: 0%;

	.operation-item-btn {
		min-width: 28px;
		height: 22px;
		color: @link01;

		&:hover {
			opacity: 0.85;
			cursor: pointer;
		}
	}
}

._button {
	display: flex;
	height: 36px;
	margin-left: 8px;
	border: 1px solid @borderColor02;
	border-radius: 6px;
	padding: 8px 16px;
	line-height: 36px;
	color: @text01;
	background: none;
	box-shadow: 0 2px 0 0 rgba(0, 0, 0, 0.04);
	justify-content: center;
	align-items: center;
	gap: 6px;
	cursor: pointer;

	&:first-child {
		margin-left: 32px;
	}

	.btn-icon {
		margin-right: 6px;
		font-size: 16px;
	}
}

.tooltip-default-text {
	overflow: hidden;
	width: 100%;
	white-space: nowrap;
	text-overflow: ellipsis;
}
</style>
